package cn.silver.framework.mybatis.service.impl;

import cn.silver.framework.core.exception.ServiceException;
import cn.silver.framework.core.model.DictModel;
import cn.silver.framework.core.utils.MapstructUtils;
import cn.silver.framework.excel.annotation.ExcelDictFormat;
import cn.silver.framework.excel.utils.PoiExcelUtil;
import cn.silver.framework.mybatis.bean.BusBean;
import cn.silver.framework.mybatis.domain.BusEntity;
import cn.silver.framework.mybatis.mapper.BusMapperPlus;
import cn.silver.framework.mybatis.param.BusParam;
import cn.silver.framework.mybatis.service.IDataService;
import cn.silver.module.configuration.service.DictService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

import static cn.silver.framework.core.constant.CacheConstants.MODEL_MAP;

/**
 * @author zhouxiaobo
 */
@Slf4j
public abstract class DataServiceImpl<M extends BusMapperPlus<T, V>, T extends BusEntity, P extends BusParam, V extends BusBean>
        extends BusServiceImpl<M, T, P, V> implements IDataService<T, P, V> {

    @Resource
    private DictService dictService;

    //TODO 数据导入逻辑需要优化
    @Override
    public int importData(MultipartFile file, P param) {
        PoiExcelUtil<V> util = new PoiExcelUtil<>(this.currentVoClass());
        Map<String, List<DictModel>> dictMap = getDictMap();
        List<V> list = null;
        try {
            list = util.importExcel(dictMap, file.getInputStream());
            int success = 0;
            for (V v : list) {
                T item = MapstructUtils.convert(v, this.getEntityClass());
                List<V> exists = this.selectList(param);
                if (CollectionUtils.isNotEmpty(exists)) {
                    V exist = exists.get(0);
                    if (item != null) {
                        item.setId(exist.getId());
                        this.baseMapper.updateById(item);
                    }
                } else {
                    if (item != null) {
                        item.preInsert();
                        this.baseMapper.insert(item);
                    }
                }
                success++;
            }
            return success;
        } catch (Exception e) {
            log.error("导入文件解析异常," + e.getMessage(), e);
            throw new ServiceException("导入文件解析异常");
        }
    }

    @Override
    public void importTemplate(HttpServletResponse response) {
        PoiExcelUtil<V> util = new PoiExcelUtil(this.currentVoClass());
        String name = this.getEntityClass().getAnnotation(Schema.class).title();
        Map<String, List<DictModel>> dictMap = getDictMap();
        util.importTemplate(name, dictMap, response);
    }

    @Override
    public void exportData(P param, HttpServletResponse response) {
        List<V> list;
        if (CollectionUtils.isNotEmpty(param.getIds())) {
            Collection<String> ids = param.getIds();
            list = this.selectByIds(ids);
        } else {
            list = this.selectList(param);
        }
        PoiExcelUtil<V> util = new PoiExcelUtil(this.currentVoClass());
        String name = this.getEntityClass().getAnnotation(Schema.class).title();
        Map<String, List<DictModel>> dictMap = getDictMap();
        util.exportExcel(list, name, dictMap, response);
//		ExcelUtil.exportExcel(list, name + "导出数据", this.currentVoClass(), response);
    }

    public Map<String, List<DictModel>> getDictMap() {
        List<ExcelDictFormat> fields = Arrays.stream(this.currentVoClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(ExcelDictFormat.class))
                .map(field -> field.getAnnotation(ExcelDictFormat.class)).toList();
        Map<String, List<DictModel>> dictMap = new HashMap<>(fields.size());
        fields.stream().filter(item -> StringUtils.isNotBlank(item.dictType())).forEach(item -> {
            dictMap.put(item.dictType(), this.dictService.getDictModelByCode(item.dictType()));
        });
        fields.stream().filter(item -> StringUtils.isNotBlank(item.contantKey())).forEach(item -> {
            dictMap.put(item.contantKey(), MODEL_MAP.get(item.contantKey()));
        });
        return dictMap;
    }
}
